package server;

import java.util.ArrayList;
import java.util.List;
import java.rmi.AccessException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import game.GameField;
import interfaceImp.ConnectNoImpl;
import interfaceImp.CurrentTurnImpl;
import interfaceImp.GameStartedImpl;
import interfaceImp.HeartbeatImpl;
import interfaceImp.ShootImpl;
import interfaces.ConnectNo;
import interfaces.CurrentTurn;
import interfaces.GameStarted;
import interfaces.Heartbeat;
import interfaces.Shoot;
import base.Starter;

public class ServerStarter extends Starter {

	private static final int _PORT =0;
	private static VectorClock clock;
	private static ArrayList getList(){
		
		ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
		classes.add(Shoot.class);
		classes.add(ConnectNo.class);
		classes.add(GameStarted.class);
		classes.add(CurrentTurn.class);
		
		//ArrayList clazzList =classes.toArray();
		return classes;
		
	}
	public ServerStarter() {
		
		super(getList());
		
		
	
	}
	static Registry registry;
	static Shoot shoot,shootStub;
	static ConnectNo con,conStub;
	static GameStarted gameState,gameStateStub;
	static CurrentTurn turn,turnStub;
	static Heartbeat beat,beatStub;
	
	 public static Object lock = new Object();
	
	private static boolean runnng;
	
	
	@Override
	public void doCustomRmiHandling() {
		
		try {
			
			//shoot
            shoot= new ShootImpl();
            shootStub = (Shoot)UnicastRemoteObject.exportObject(shoot,_PORT);
            //connectNo
            con = new ConnectNoImpl();
            conStub = (ConnectNo)UnicastRemoteObject.exportObject(con,_PORT);
			//gamestarted
            gameState = new GameStartedImpl();
            gameStateStub=(GameStarted)UnicastRemoteObject.exportObject(gameState, _PORT);
			//currentTurn
            turn = new CurrentTurnImpl();
            turnStub=(CurrentTurn)UnicastRemoteObject.exportObject(turn, _PORT);
            //heartbeat
            beat = new HeartbeatImpl();
            beatStub = (Heartbeat)UnicastRemoteObject.exportObject(beat, _PORT);
            
            
            registry = LocateRegistry.getRegistry();
            registry.rebind(ConnectNo.SERVICE_NAME, conStub);
            registry.rebind(Shoot.SERVICE_NAME, shootStub);
            registry.rebind(GameStarted.SERVICE_NAME, gameStateStub);
            registry.rebind(CurrentTurn.SERVIC_NAME,turnStub);
            registry.rebind(Heartbeat.SERVICE_NAME, beatStub);
            System.out.println("Server Bound!");
            setClock(VectorClock.getInstance());
            //turn.setCurrentTurn(1,0);
        }
        catch(Exception e) {
            e.printStackTrace();
        }
		
	}
    public static void main(String[] args) throws Exception {
        new ServerStarter();
        GameField game = new GameField();
        int beatCounter1 = 0;
        int beatCounter2 = 0;
        int beatCounter3 = 0;
        int beatCounter4 = 0;
		
        synchronized (lock) {
			
		}shoot.setMainTab(game.getTab());
        System.out.println("Number of players: " + con.getCon());
        con.setCon(0);
        while(!runnng)
        {
        	setClock(VectorClock.getInstance());
//        	if(!clock.list.get(0).isEmpty())
//        		System.out.println(clock.list.get(0).get(0).getTimestamp() + " " + 
//        				clock.list.get(0).get(0).getId( )+  " " + clock.list.get(0).get(0).getService());
        	synchronized(lock)
        	{
        		//checking if client crashed:
        		//if(gameState.isReady())
        		{
        		//ONE	
        			if(beat.isBeat1())
        			{//System.out.println("BEEP FROM ONE!" + beatCounter1);
        				beat.setBeat1(false);
        				beatCounter1=0;
        			}
        			else
        			{
        				beatCounter1++;
        				if(beatCounter1>100)
        				{
        					if(gameState.isReady())
        					{
        						if(turn.getCuttentTurn(0) == 1)
        						{
        							turn.setCurrentTurn(2,0);
        							System.out.println("Player 1 omited!");
        						}
        					}
        				}
        			}
        		//TWO	
        			if(beat.isBeat2())
        			{//System.out.println("BEEP FROM ONE!" + beatCounter1);
        				beat.setBeat2(false);
        				beatCounter2=0;
        			}
        			else
        			{
        				beatCounter2++;
        				if(beatCounter2>100)
        				{
        					if(gameState.isReady())
        					{
        						if(turn.getCuttentTurn(0) == 2)
        						{
        							turn.setCurrentTurn(3,0);
        							System.out.println("Player 2 omited!");
        						}
        					}
        				}
        			}
        		//THREE	
        			if(beat.isBeat3())
        			{//System.out.println("BEEP FROM ONE!" + beatCounter1);
        				beat.setBeat3(false);
        				beatCounter3=0;
        			}
        			else
        			{
        				beatCounter3++;
        				if(beatCounter3>100)
        				{
        					if(gameState.isReady())
        					{
        						if(turn.getCuttentTurn(0) == 3)
        						{
        							turn.setCurrentTurn(4,0);
        							System.out.println("Player 3 omited!");
        						}
        					}
        				}
        			}
        		//FOUR	
        			if(beat.isBeat4())
        			{//System.out.println("BEEP FROM ONE!" + beatCounter1);
        				beat.setBeat4(false);
        				beatCounter4=0;
        			}
        			else
        			{
        				beatCounter4++;
        				if(beatCounter4>100)					
        				{
        					if(gameState.isReady())
        					{
        						if(turn.getCuttentTurn(0) == 4)
        						{
        							turn.setCurrentTurn(1,0);
        							System.out.println("Player 4 omited!");
        						}
        					}
        				}
        			}
        			if(beatCounter1>200&& beatCounter2>200 && beatCounter3> 200 && beatCounter4> 200 && gameState.isReady())
        			{
        				System.out.println("Game ended Noone won coz every1 dc'ded" );
    					gameState.setOff();
    					break;
        			}
        			
        			
        		}
        		
        		
        		
        		//
        	if(!gameState.isReady()){
        		game.setTab(shoot.getMainTab());
        		int counter=0;
        		for(int j=0;j<game.getTab().length;j++)
        			for(int i=0;i< game.getTab().length;i++)
        			{
        				if( game.getTab()[j][i]!=0)
        				{
        					counter++;
        				}
        			}
        		if(counter >=16)
        		{
        			synchronized (lock) {
					
					System.out.println("GAME ON!");
        			gameState.setOn();
        			}
        		}
        		}
        	}
        	if(gameState.isReady())
        	{
        		synchronized (lock) {
					game.setTab(shoot.getMainTab());
					int counter=0;
	        		for(int j=0;j<game.getTab().length;j++)
	        			for(int i=0;i< game.getTab().length;i++)
	        			{
	        				if( game.getTab()[j][i]==3)
	        				{
	        					counter++;
	        				}
	        			}
	        				if(threeDead() && gameState.isReady())
	        				{
	        					System.out.println("Game ended winner is player " + whoWon() );
	        					gameState.setOff();
	        					//printClock();
	        					break;
	        					//System.exit(0);
	        				}
				}
        	}
//        	if(con.getCon()>3 && !changed)
//        	{
//        		System.out.println("I have full set of players!");
//        		changed= !changed;
//        	}
        	
        	
        	
        }
    }
   // private String allDead
    public static boolean threeDead() throws RemoteException
    {
    	
    	int Threedied=0;
    	int c1,c2,c3,c4;
    	c1=0;c2=0;c3=0;c4=0;
    	int[][] tab= shoot.getMainTab();
    	for(int i=0;i<10;i++)
	           for(int j=0;j<10;j++)
	        	   if(tab[i][j]==2)
	        		   c1++;
		 for(int i=10;i<20;i++)
	           for(int j=0;j<10;j++)
	        	   if(tab[i][j]==2)
	        		   c2++;
		 for(int i=10;i<20;i++)
	           for(int j=10;j<20;j++)
	        	   if(tab[i][j]==2)
	        		   c3++;
		 for(int i=0;i<10;i++)
	           for(int j=10;j<20;j++)
	        	   if(tab[i][j]==2)
	        		   c4++;
    	if(c1==4){ Threedied++;}
    	if(c2==4){ Threedied++;}
    	if(c3==4){ Threedied++;}
    	if(c4==4){ Threedied++;}
    	if(Threedied>=3)
    		return true;
    		else
    			return false;
    }
    public static String whoWon() throws RemoteException
    {
    	int c1,c2,c3,c4;
    	c1=0;c2=0;c3=0;c4=0;
    	String winner = "noone";
    	int[][] tab= shoot.getMainTab();
    	for(int i=0;i<10;i++)
	           for(int j=0;j<10;j++)
	        	   if(tab[i][j]==2)
	        		   c1++;
		 for(int i=10;i<20;i++)
	           for(int j=0;j<10;j++)
	        	   if(tab[i][j]==2)
	        		   c2++;
		 for(int i=10;i<20;i++)
	           for(int j=10;j<20;j++)
	        	   if(tab[i][j]==2)
	        		   c3++;
		 for(int i=0;i<10;i++)
	           for(int j=10;j<20;j++)
	        	   if(tab[i][j]==2)
	        		   c4++;
		 if(c1<4)winner ="One";
		 else if(c2<4) winner="Two";
		 else if(c3<4) winner ="Three";
		 else if(c4<4) winner = "Four";
		 
		 return winner;
    }
	public static synchronized void setClock(VectorClock clock2) {
		clock = clock2;
	}
	public static synchronized VectorClock getClock() {
		return clock;
	}
	
	public static void printClock()
	{
		for(int i=0;i<clock.list.size();i++)
		{
			System.out.println("\n=========================================================================");
			System.out.println("Clock for client " + (i+1));
			
			for(int j=0;j<clock.list.get(i).size();j++)
			{
				System.out.print("("+clock.list.get(i).get(j).getTimestamp() + "." + 
       				clock.list.get(i).get(j).getId( )+  "," + clock.list.get(i).get(j).getService()+")");
				if(j>0 && j<=clock.list.get(i).size()-1) System.out.print("->");
			}
			System.out.println("=========================================================================");
		}
	}

}
